package com.optitronics.beans;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.Table;
import javax.persistence.TableGenerator;
import javax.persistence.TypedQuery;
import javax.persistence.Version;

import org.hibernate.annotations.Formula;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.transaction.annotation.Transactional;

import com.optitronics.ui.ResellerOrderDisplayForm;
import com.optitronics.util.OptitronicsConstants;

@Configurable
@Entity
@Table(name = "reseller_orders")
public class ResellerOrder {

	@PersistenceContext
	transient EntityManager entityManager;

	@Id
	@TableGenerator(name = "resellerOrderGenerator", pkColumnValue = "RESELLER_ORDERS", table = OptitronicsConstants.COUNTER_TABLE_NAME, pkColumnName = OptitronicsConstants.COUNTER_PK_COLUMN_NAME, valueColumnName = OptitronicsConstants.COUNTER_VALUE_COLUMN_NAME, allocationSize = OptitronicsConstants.COUNTER_ALLOCATION_SIZE)
	@GeneratedValue(strategy = GenerationType.TABLE, generator = "resellerOrderGenerator")
	@Column(name = "ID")
	private Integer id;

	@ManyToOne
	@JoinColumn(name = "RESELLER_ID", referencedColumnName = "ID")
	private Reseller reseller;

	@Version
	@Column(name = "VERSION")
	private Integer version;

	@Column(name = "ORDER_DATE")
	private Date orderDate;

	@Column(name = "ORDER_NUMBER")
	private String orderNumber;

	@Formula(" ( SELECT SUM(oi.AMOUNT_WITHOUT_TAX) FROM order_items oi WHERE oi.RESELLER_ORDER_ID = ID ) ")
	private BigDecimal totalAmountWithoutTax;

	@Formula(" ( SELECT SUM(oi.AMOUNT_WITH_TAX) FROM order_items oi WHERE oi.RESELLER_ORDER_ID = ID ) ")
	private BigDecimal totalAmountWithTax;

	public static String generateOrderNumber() {
		Date now = new Date();

		SimpleDateFormat format = new SimpleDateFormat(OptitronicsConstants.INVOICE_DATE_TIME_FORMAT);
		return OptitronicsConstants.INVOICE_PREFIX + format.format(now);
	}

	@Transactional
	public void persist() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.persist(this);
	}

	@Transactional
	public void flush() {
		if (this.entityManager == null)
			this.entityManager = entityManager();
		this.entityManager.flush();
	}

	public static final EntityManager entityManager() {
		EntityManager em = new ResellerOrder().entityManager;
		if (em == null)
			throw new IllegalStateException(
					"Entity manager has not been injected (is the Spring Aspects JAR configured as an AJC/AJDT aspects library?)");
		return em;
	}

	public static long countResellerOrders(Integer resellerId) {

		String queryString = "SELECT COUNT(o) from ResellerOrder o";
		if (resellerId != null) {
			queryString += " WHERE o.reseller.id = :resellerId";
		}

		TypedQuery<Long> query = entityManager().createQuery(queryString, Long.class);
		if (resellerId != null) {
			query.setParameter("resellerId", resellerId);
		}

		return query.getSingleResult();
	}

	public static ResellerOrder findResellerOrder(Integer id) {
		if (id == null)
			return null;
		return entityManager().find(ResellerOrder.class, id);
	}

	@SuppressWarnings("unchecked")
	public static List<ResellerOrderDisplayForm> findResellerOrderEntries(Integer resellerId, int firstResult,
			int maxResults) {

		String queryString = "SELECT new com.optitronics.ui.ResellerOrderDisplayForm(o) from ResellerOrder o ";
		if (resellerId != null) {
			queryString += " WHERE o.reseller.id = :resellerId";
		}
		queryString += " ORDER BY o.id DESC";

		Query query = entityManager().createQuery(queryString);
		query.setFirstResult(firstResult).setMaxResults(maxResults);
		if (resellerId != null) {
			query.setParameter("resellerId", resellerId);
		}

		return query.getResultList();
	}

	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public Reseller getReseller() {
		return this.reseller;
	}

	public void setReseller(Reseller reseller) {
		this.reseller = reseller;
	}

	public Integer getVersion() {
		return this.version;
	}

	public void setVersion(Integer version) {
		this.version = version;
	}

	public Date getOrderDate() {
		return this.orderDate;
	}

	public void setOrderDate(Date orderDate) {
		this.orderDate = orderDate;
	}

	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("Reseller: ").append(getReseller()).append(", ");
		sb.append("Version: ").append(getVersion()).append(", ");
		sb.append("OrderDate: ").append(getOrderDate()).append(", ");
		sb.append("Id: ").append(getId());
		return sb.toString();
	}

	public BigDecimal getTotalAmountWithoutTax() {
		return totalAmountWithoutTax;
	}

	public void setTotalAmountWithoutTax(BigDecimal totalAmountWithoutTax) {
		this.totalAmountWithoutTax = totalAmountWithoutTax;
	}

	public BigDecimal getTotalAmountWithTax() {
		return totalAmountWithTax;
	}

	public void setTotalAmountWithTax(BigDecimal totalAmountWithTax) {
		this.totalAmountWithTax = totalAmountWithTax;
	}

	public String getOrderNumber() {
		return orderNumber;
	}

	public void setOrderNumber(String orderNumber) {
		this.orderNumber = orderNumber;
	}
}
